package de.tabuma.lib.webservice.wsdl;

import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.logging.*;

/**
 * @author $Author: alefen $
 * @version $Revision: 1.1.1.1.6.1 $
 * @since $Date: 2010/01/13 10:17:03 $
 */
public class TypeFacade {

    private static final Logger log = Logger.getLogger(TypeFacade.class.getName());

    public static String getType(String namespace,Hashtable<String,Class> methodTable) {
        String str = "";
        str += "\t<types>\n";
        str += "\t\t<xsd:schema targetNamespace=\""+namespace+"\">\n";
        Enumeration<String> enu = methodTable.keys();
        while(enu.hasMoreElements()) {
            String key = enu.nextElement();
            Class clazz = methodTable.get(key);
            str += getType(key, clazz);
        }
        str += "\t\t</xsd:schema>\n";
        str += "\t</types>\n";
        return str;
    }

    public static String getType(String name, Class clazz) {
        String str = "";
        Method[] mList = clazz.getDeclaredMethods();
        for(int i=0;i<mList.length;i++) {
            str += getType(name, mList[i]);
        }
        return str;
    }

    public static String getType(String name, Method method) {
        String str = "";

        Class[] methodParams = method.getParameterTypes();
        if(methodParams.length>0) {
            str += "<xsd:element name=\"Request_"+name+"_"+method.getName()+"\">\n";
            str += "<xsd:complexType>\n";
            str += "<xsd:sequence>";
        }
        for(int i=0;i<methodParams.length;i++) {
            Class clazz = methodParams[i];
            if(clazz.isPrimitive() || clazz.getSimpleName().equals("String")) {
                str += getType1(clazz.getSimpleName()+(i+1),clazz, null);
            }
            else {
                str += "<xsd:element name=\""+clazz.getSimpleName()+(i+1)+"\">\n";
                str += getType1(clazz.getSimpleName()+(i+1),clazz, null);
                str += "</xsd:element>\n";
            }
        }
        if(methodParams.length>0) {
            str += "</xsd:sequence>";
            str += "</xsd:complexType>\n";
            str += "</xsd:element>\n";
        }
        
        Class response = (Class) method.getReturnType();
        Type responseType = method.getGenericReturnType();
        if(response!=null) {
            if(!response.getName().equals("void")) {
                str += "<xsd:element name=\"Response_"+name+"_"+method.getName()+"\">\n";
                str += "<xsd:complexType>\n";
                str += "<xsd:sequence>\n";
                if(response.isPrimitive() || response.getSimpleName().equals("String")) {
                    str += getType1(response.getSimpleName(),response, responseType);
                }
                else {
                    str += "<xsd:element name=\""+response.getSimpleName()+"\">\n";
                    str += getType1(response.getSimpleName(),response, responseType);
                    str += "</xsd:element>\n";
                }
                str += "</xsd:sequence>\n";
                str += "</xsd:complexType>\n";
                str += "</xsd:element>\n";
            
        
                str += "<xsd:element name=\"Exception_"+name+"_"+method.getName()+"\">\n";
                str += "<xsd:complexType>\n";
                str += "<xsd:sequence>\n";
                str += "<xsd:element name=\"ExceptionClass\" type=\"xsd:string\"/>\n";
                str += "<xsd:element name=\"ExceptionCause\" type=\"xsd:string\"/>\n";
                str += "<xsd:element name=\"ExceptionMessage\" type=\"xsd:string\"/>\n";
                str += "</xsd:sequence>\n";
                str += "</xsd:complexType>\n";
                str += "</xsd:element>\n";
            }
        }
        return str;
    }
    
    public static String getType1(String name, Class clazz, Type type) {
        String str = "";
        if(clazz.isPrimitive() || clazz.getSimpleName().equals("String")) {
            str += getElement(name, clazz);
        }
        else {
            if(clazz==java.util.List.class || clazz==java.util.Vector.class) {
                str += "<xsd:complexType>\n";
                if(type!=null) {
                    if(type instanceof ParameterizedType){
                        str += "<xsd:sequence>";
                        str += "<xsd:element name=\""+name+"\" minOccurs=\"0\" maxOccurs=\"unbounded\">";
                        ParameterizedType type1 = (ParameterizedType) type;
                        Type[] typeArguments = type1.getActualTypeArguments();
                        for(int i=0;i<typeArguments.length;i++) {
                            Class clazz1 = (Class) typeArguments[i];
                            str += getType1(clazz1.getSimpleName(), clazz1, null);
                        }
                        str += "</xsd:element>";
                        str += "</xsd:sequence>";
                    }
                }
                str += "</xsd:complexType>\n";
            }
            else {
                str += "<xsd:complexType>\n";
                str += "<xsd:sequence>";
                for(int i=0;i<clazz.getDeclaredFields().length;i++) {
                    String name1 = clazz.getDeclaredFields()[i].getName().toLowerCase();
                    if(name1.indexOf("jdo")!=0 && name1.indexOf("serialversion")!=-1) {
                        str += getElement(name1,clazz.getDeclaredFields()[i].getType());
                    }
                }
                str += "</xsd:sequence>";
                str += "</xsd:complexType>\n";
            }
        }
        return str;
    }
    
    public static String getElement(String name, Class clazz) {
        String str = "";
        if(clazz.isInstance(java.util.List.class) || clazz.isInstance(java.util.Vector.class)) {
            str += "<xsd:complexType>\n";
            Annotation annotation[] = clazz.getAnnotations();
            for(int i=0;i<annotation.length;i++) {
                Class list = annotation[i].annotationType();
                for(int j=0;j<list.getDeclaredFields().length;i++) {
                    Field myField = list.getDeclaredFields()[i];
                    str += getElement(myField.getName(), myField.getDeclaringClass());
                }
            }
            str += "</xsd:complexType>\n";
        }
        else {
            str += "<xsd:element name=\""+name+"\" type=\"xsd:"+clazz.getSimpleName().toLowerCase()+"\"/>";
        }
        return str;
    }

    public static String getComplexType(Class clazz) {
        String str = "";
        return str;
    }
}